﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Data;
using System.Windows;
using System.Windows.Threading;
using snat.model;

namespace gui {

    /// <summary>
    /// Contains StepType for the Play Control step drop down box
    /// Catergories for Stepping Through the Model:
    /// Catergory 1 = Steps / Messages
    /// Catergory 2 = Time in Days
    /// Catergory 3 = Time is Hours
    /// Catergory 4 = Time in Minutes
    /// Catergory 5 = Time in Seconds
    /// </summary>
    public class StepType {
        public string Type { get; set; }
        public int Catergory { get; set; }
        public StepType(string type, int catergory) {
            Type = type;
            Catergory = catergory;
        }
    }


    /// <summary>
    /// GUI Notifiable Play Control Class
    /// Contains model time, progress percentage, number of nodes
    /// number of edges and number of messages
    /// </summary>
    public class PlayControlConnect : DependencyObject, INotifyPropertyChanged {

        public static PlayControlConnect Instance;
        public static Dispatcher _Dispatcher { get; set; }

        // Network Properties
        public static DependencyProperty ModelTimeProperty = DependencyProperty.Register("ModelTime", typeof(string), typeof(PlayControlConnect));
        public static DependencyProperty ProgressPercentageProperty = DependencyProperty.Register("ProgressPercentage", typeof(string), typeof(PlayControlConnect));
        public static DependencyProperty NumNodesProperty = DependencyProperty.Register("NumNodes", typeof(int), typeof(PlayControlConnect));
        public static DependencyProperty NumEdgesProperty = DependencyProperty.Register("NumEdges", typeof(int), typeof(PlayControlConnect));
        public static DependencyProperty NumMessagesProperty = DependencyProperty.Register("NumMessages", typeof(int), typeof(PlayControlConnect));


        static PlayControlConnect() {

            // Build Combo Box
            IList<StepType> list = new List<StepType>();
            list.Add(new StepType("Messages", 1));
            list.Add(new StepType("Days", 2));
            list.Add(new StepType("Hours", 3));
            list.Add(new StepType("Minutes", 4));
            list.Add(new StepType("Seconds", 5));
            stepTypeList = new CollectionView(list);

            // Create Instance
            Instance = new PlayControlConnect();
            Instance.Clean();
        }

        // Step Type List Combo Box
        private static readonly CollectionView stepTypeList;
        public static CollectionView StepTypeList {
            get { return stepTypeList; }
        }
        private static string step;
        public string Step {
            get { return step; }
            set {
                if (step == value) return;
                step = value;
                OnPropertyChanged("StepType");
            }
        }

        // Default "Clean" Values
        public void Clean() {
            Instance.ModelTime = "Uninitialised";
            Instance.ProgressPercentage = "0 %";
            Instance.NumNodes = 0;
            Instance.NumEdges = 0;
            Instance.NumMessages = 0;
        }

        public static void UpdateTimeNow() {
            if (_Dispatcher != null) {
                _Dispatcher.BeginInvoke(
                     DispatcherPriority.Send,
                    new Action(delegate() {
                    Instance.ModelTime = String.Join(" ", NetworkModel.Instance.CurrentTime.ToShortDateString(),
                                                        NetworkModel.Instance.CurrentTime.ToShortTimeString());
                    Instance.ProgressPercentage = String.Join(" ", ((int)(NetworkModel.Instance.TapePercentagePlayed * 10000))/100, "%");
                }));
            }
        }

        public static void Initialising() {
            if (_Dispatcher != null) {
                _Dispatcher.BeginInvoke(
                     DispatcherPriority.Send,
                    new Action(delegate() {
                    Instance.ModelTime = String.Join(" ", NetworkModel.Instance.CurrentTime.ToShortDateString(),
                                                        NetworkModel.Instance.CurrentTime.ToShortTimeString());
                    Instance.ProgressPercentage = "0 % (Building)";
                }));
            }
        }

        public static void Initialised() {
            if (_Dispatcher != null) {
                _Dispatcher.BeginInvoke(
                     DispatcherPriority.Send,
                    new Action(delegate() {
                    Instance.ModelTime = String.Join(" ", NetworkModel.Instance.CurrentTime.ToShortDateString(),
                                                        NetworkModel.Instance.CurrentTime.ToShortTimeString());
                    Instance.ProgressPercentage = "0 % (Ready)";
                }));
            }
        }

        // Network Property Update Methods
        public static void IncrementNodeCount() {
            if (_Dispatcher != null) {
                _Dispatcher.BeginInvoke(
                     DispatcherPriority.Send,
                    new Action(delegate() {
                    Instance.NumNodes++;
                }));
            }
        }

        public static void IncrementEdgeCount() {
            if (_Dispatcher != null) {
                _Dispatcher.BeginInvoke(
                     DispatcherPriority.Send,
                    new Action(delegate() {
                    Instance.NumEdges++;
                }));
            }
        }

        public static void IncrementMessageCount() {
            if (_Dispatcher != null) {
                _Dispatcher.BeginInvoke(
                     DispatcherPriority.Send,
                    new Action(delegate() {
                    Instance.NumMessages++;
                }));
            }
        }

        public static void Reset() {
            if (_Dispatcher != null) {
                _Dispatcher.BeginInvoke(
                     DispatcherPriority.Send,
                    new Action(delegate() {
                    Instance.ModelTime = String.Join(" ", NetworkModel.Instance.StartTime.ToShortDateString(),
                                                        NetworkModel.Instance.StartTime.ToShortTimeString());
                    Instance.ProgressPercentage = "0 % (Resetting)";
                    Instance.NumMessages = 0;
                    Instance.NumEdges = 0;
                }));
            }
        }

        // NetworkModel Properties
        public string ModelTime {
            get { return (string)GetValue(ModelTimeProperty); }
            set { SetValue(ModelTimeProperty, value); }
        }

        public string ProgressPercentage {
            get { return (string)GetValue(ProgressPercentageProperty); }
            set { SetValue(ProgressPercentageProperty, value); }
        }

        public int NumNodes {
            get { return (int)GetValue(NumNodesProperty); }
            set { SetValue(NumNodesProperty, value); }
        }

        public int NumEdges {
            get { return (int)GetValue(NumEdgesProperty); }
            set { SetValue(NumEdgesProperty, value); }
        }

        public int NumMessages {
            get { return (int)GetValue(NumMessagesProperty); }
            set { SetValue(NumMessagesProperty, value); }
        }

        private void OnPropertyChanged(string propertyName) {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}
